package com.atguigu.gulimall.search.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 *创建线程的4钟方式
 * 1.继承Thread类
 * 2.实现Runnable 接口
 * 3.实现Callable 接口 + futureTask (可以拿到返回结果，可以处理异常)
 * 4.线程池
 *   创建线程池
 *      1. Executors 工具类
 *
 * 区别
 *  1.2 不能得到返回值
 *  3 可以返回值
 *  1.2.3 都不能控制资源
 *  4 可以控制资源 性能稳定
 */
public class ThreadTest {

    /**
     * 线程池
     * Executors.newCachedThreadPool(); code是0 所有都可回收
     * Executors.newFixedThreadPool();  固定大小 code = max； 都不可回收
     * Executors.newScheduledThreadPool(); 定时任务的线程池
     * Executors.newSingleThreadExecutor(); 单线程的线程池，后台从队列获取任务 挨个执行
     */
    public static ExecutorService executorService = Executors.newFixedThreadPool(10);


    //继承Thread类
    public static class Thread01 extends Thread{

        @Override
        public void run() {
            System.out.println("当前线程 -> "+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果 -> "+i);
        }
    }
    //实现Runnable 接口
    public static class Thread02 implements Runnable{

        @Override
        public void run() {
            System.out.println("当前线程 -> "+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果 -> "+i);
        }
    }
    //实现Callable 接口
    public static class Thread03 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程 -> "+Thread.currentThread().getId());
            int i = 10/2;
            System.out.println("运行结果 -> "+i);
            return i;
        }
    }
    //线程池
    public static class Thread04{

    }

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main ...  start...");

//        Thread01 thread01 = new Thread01();
//        thread01.start();

//        Thread02 thread02 = new Thread02();
//        new Thread(thread02).start();

//        FutureTask task = new FutureTask<>(new Thread03());
//        new Thread(task).start();
//        //等待线程执行完成 获取返回结果  阻塞等待
//        Integer o = (Integer) task.get();
//        System.out.println("返回结果 -> "+o);

        //当前系统中 线程池只有一两个  每个异步任务都提交给线程池去执行
        //executorService.execute(new Thread02());


        /**
         * 七大参数
         * int corePoolSize,  核心线程数  线程池创建好以后就准备就绪的线程数量 就等待来接收异步任务去执行
         * int maximumPoolSize, 最大线程数量 控制资源并发
         * long keepAliveTime, 存活时间 如果当前线程大于核心线程数量  释放空闲线程(maximumPoolSize-corePoolSize)  只要线程空闲大于指定的keepAliveTime
         * TimeUnit unit, 时间单位
         * BlockingQueue<Runnable> workQueue, 阻塞队列 如果任务有很多就会将目前多的任务放在队列里面 只要有线程空闲了 就会从队列里面取出新的任务继续执行
         * ThreadFactory threadFactory, 线程的创建工厂
         * RejectedExecutionHandler handler 如果队列满了 按照我们指定的拒绝策略拒绝执行任务
         *
         * 工作顺序
         *  1.线程池创建，准备好core数量的核心线程，准备好接受任务
         *  2.core满了，就将再进来的任务放入阻塞队列中，空闲的core就会自己去阻塞队列获取任务执行
         *  3.阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
         *  4.max 满了就用RejectedExecutionHandler拒绝任务
         *  5.max 都执行完成，又很多空闲。在指定的时间keepAliveTime以后 释放max- core 这些线程
         *  6.new linkedBlockingDeque<>()：默认是Integer 的最大值  内存不够问题
         *    一个线程池 core 7 ; max 20 queue 50  ,100并发进来怎末分配的
         *    7个会立即得到执行，50个会进入队列， 再开13个进行执行， 剩下的30个就使用拒绝策略
         *  如果不想抛弃 还要执行 callerRunsPolicy
         */
//        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
//                200,
//                10,
//                TimeUnit.SECONDS,
//                new LinkedBlockingDeque<>(100000),
//                Executors.defaultThreadFactory(),
//                new ThreadPoolExecutor.AbortPolicy()
//        );
//        executor.execute(new Thread02());


        //runAsync
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程 -> " + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println("运行结果 -> " + i);
//        }, executorService);

        //方法完成后的感知
//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程 -> " + Thread.currentThread().getId());
//            int i = 10 / 0;
//            System.out.println("运行结果 -> " + i);
//            return i;
//        }, executorService).whenComplete((res,exceuption)->{
//            //虽然能得到异常信息，但是没办法修改返回数据。
//            System.out.println("异步任务执行完成,结果是:"+res+"异常是:"+exceuption);
//        }).exceptionally(throwable->{
//            //可以感知异常 同时返回默认值
//            return 10;
//        });

        //方法执行完成后的处理
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程 -> " + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果 -> " + i);
            return i;
        }, executorService).handle((res,thr)->{
            if (res != null)  return res*2;
            if (thr != null)  return 0;
            return 0;
        });


        Integer integer = future.get();
        System.out.println("结果-> "+integer);
        System.out.println("main ...  end...");
    }


}
